1 module hip.graphics.g2d.renderer2d; 2 3 version(Have_bindbc_lua) version = HipremeEngineLua; 4 5 import hip.graphics.g2d.spritebatch; 6 import hip.graphics.g2d.tilemap; 7 import hip.graphics.g2d.geometrybatch; 8 import hip.graphics.orthocamera; 9 import hip.hiprenderer; 10 import hip.bind.interpreters; 11 public import hip.api.graphics.color; 12 public import hip.api.data.commons:IHipAssetLoadTask; 13 public import hip.graphics.g2d.textrenderer; 14 public import hip.api.renderer.viewport; 15 16 public import hip.api.data.font; 17 18 private __gshared 19 { 20 IHipTexture defaultTexture; 21 HipSpriteBatch spBatch; 22 GeometryBatch geoBatch; 23 HipTextRenderer textBatch; 24 HipOrthoCamera camera; 25 Viewport viewport; 26 HipTextRenderer textRenderer; 27 IHipBatch lastBatch; 28 bool autoUpdateCameraAndViewport; 29 float sharedDepth = 0; 30 } 31 32 void manageBatchChange(IHipBatch newBatch) 33 { 34 if(lastBatch !is null && lastBatch !is newBatch) 35 { 36 sharedDepth+= 0.1; 37 lastBatch.draw(); 38 39 if(newBatch !is null) 40 newBatch.setCurrentDepth(sharedDepth); 41 } 42 lastBatch = newBatch; 43 } 44 45 46 import hip.console.log; 47 void initialize(HipInterpreterEntry entry = HipInterpreterEntry.init, bool shouldAutoUpdateCameraAndViewport = true) 48 { 49 autoUpdateCameraAndViewport = shouldAutoUpdateCameraAndViewport; 50 hiplog("2D Renderer: Initializing viewport"); 51 viewport = new Viewport(0, 0, HipRenderer.width, HipRenderer.height); 52 viewport.setWorldSize(HipRenderer.width, HipRenderer.height); 53 viewport.setType(ViewportType.fit, HipRenderer.width, HipRenderer.height); 54 HipRenderer.setViewport(viewport); 55 hiplog("2D Renderer: Initializing camera"); 56 camera = new HipOrthoCamera(); 57 camera.setSize(viewport.worldWidth, viewport.worldHeight); 58 59 hiplog("2D Renderer: Initializing spritebatch"); 60 spBatch = new HipSpriteBatch(camera); 61 hiplog("2D Renderer: Initializing geometrybatch"); 62 geoBatch = new GeometryBatch(camera); 63 hiplog("2D Renderer: Initializing text renderer"); 64 textBatch = new HipTextRenderer(camera); 65 setGeometryColor(HipColor.white); 66 67 68 version(HipremeEngineLua) 69 { 70 hiplog("2D Renderer: sending lua functions"); 71 if(entry != HipInterpreterEntry.init) 72 { 73 sendInterpreterFunc!(setGeometryColor)(entry.intepreter); 74 sendInterpreterFunc!(drawPixel)(entry.intepreter); 75 sendInterpreterFunc!(drawRectangle)(entry.intepreter); 76 sendInterpreterFunc!(drawTriangle)(entry.intepreter); 77 sendInterpreterFunc!(fillRectangle)(entry.intepreter); 78 sendInterpreterFunc!(fillEllipse)(entry.intepreter); 79 sendInterpreterFunc!(drawEllipse)(entry.intepreter); 80 sendInterpreterFunc!(fillTriangle)(entry.intepreter); 81 sendInterpreterFunc!(drawLine)(entry.intepreter); 82 sendInterpreterFunc!(drawQuadraticBezierLine)(entry.intepreter); 83 // sendInterpreterFunc!(drawText)(entry.intepreter); not supported yet 84 } 85 } 86 87 } 88 89 /** 90 * This resizes both the 2D renderer viewport and its Orthographic Camera, maintaining always the 91 * correct aspect ratio 92 */ 93 void resizeRenderer2D(uint width, uint height) 94 { 95 if(autoUpdateCameraAndViewport) 96 { 97 if(viewport !is null && HipRenderer.getCurrentViewport() == viewport) 98 HipRenderer.setViewport(viewport); 99 if(camera !is null) 100 camera.setSize(viewport.worldWidth, viewport.worldHeight); 101 } 102 } 103 104 export extern(System): 105 106 107 int[2] getWindowSize(){return [HipRenderer.width, HipRenderer.height];} 108 109 void setWindowSize(uint width, uint height) 110 { 111 HipRenderer.setWindowSize(width, height); 112 HipRenderer.setViewport(viewport); 113 camera.setSize(cast(int)viewport.worldWidth,cast(int)viewport.worldHeight); 114 } 115 void setCameraSize(uint width, uint height){camera.setSize(width, height);} 116 void setViewport(Viewport v) 117 { 118 HipRenderer.setViewport(v); 119 } 120 void setStencilTestingEnabled(bool bEnable) 121 { 122 manageBatchChange(null); 123 HipRenderer.setStencilTestingEnabled(bEnable); 124 } 125 void setStencilTestingMask(uint mask) 126 { 127 manageBatchChange(null); 128 HipRenderer.setStencilTestingMask(mask); 129 } 130 void setRendererColorMask(ubyte r, ubyte g, ubyte b, ubyte a) 131 { 132 manageBatchChange(null); 133 HipRenderer.setColorMask(r,g,b,a); 134 } 135 void setStencilTestingFunction(HipStencilTestingFunction passFunc, uint reference, uint mask) 136 { 137 manageBatchChange(null); 138 HipRenderer.setStencilTestingFunction(passFunc, reference, mask); 139 } 140 void setStencilOperation(HipStencilOperation stencilFail, HipStencilOperation depthFail, HipStencilOperation stencilAndDephPass) 141 { 142 manageBatchChange(null); 143 HipRenderer.setStencilOperation(stencilFail, depthFail, stencilAndDephPass); 144 } 145 Viewport getCurrentViewport() 146 { 147 import hip.util.lifetime; 148 return cast(typeof(return))hipSaveRef(HipRenderer.getCurrentViewport()); 149 } 150 151 void setRendererErrorCheckingEnabled(bool enable) 152 { 153 HipRenderer.setErrorCheckingEnabled(enable); 154 } 155 void setGeometryColor(const HipColor color){geoBatch.setColor(color);} 156 void drawPixel(int x, int y, HipColor color = HipColor.no) 157 { 158 manageBatchChange(geoBatch); 159 geoBatch.drawPixel(x, y,color); 160 } 161 void drawRectangle(int x, int y, int w, int h, HipColor color = HipColor.no) 162 { 163 manageBatchChange(geoBatch); 164 geoBatch.drawRectangle(x,y,w,h,color); 165 } 166 void drawTriangle(int x1, int y1, int x2, int y2, int x3, int y3, HipColor color = HipColor.no) 167 { 168 manageBatchChange(geoBatch); 169 geoBatch.drawTriangle(x1,y1,x2,y2,x3,y3,color); 170 } 171 void drawEllipse(int x, int y, int radiusW, int radiusH, int degrees = 360, HipColor color = HipColor.no, int precision = 24) 172 { 173 manageBatchChange(geoBatch); 174 geoBatch.drawEllipse(x,y,radiusW,radiusH,degrees,color,precision); 175 } 176 void drawLine(int x1, int y1, int x2, int y2, HipColor color = HipColor.no) 177 { 178 manageBatchChange(geoBatch); 179 geoBatch.drawLine(x1,y1,x2,y2,color); 180 } 181 void drawQuadraticBezierLine(int x0, int y0, int x1, int y1, int x2, int y2, int precision=24, HipColor color = HipColor.no) 182 { 183 manageBatchChange(geoBatch); 184 geoBatch.drawQuadraticBezierLine(x0,y0,x1,y1,x2,y2,precision,color); 185 } 186 void fillRectangle(int x, int y, int w, int h, HipColor color = HipColor.no) 187 { 188 manageBatchChange(geoBatch); 189 geoBatch.fillRectangle(x,y,w,h,color); 190 } 191 void fillRoundRect(int x, int y, int w, int h, int radius = 4, HipColor color = HipColor.no, int precision = 16) 192 { 193 manageBatchChange(geoBatch); 194 geoBatch.fillRoundRect(x,y,w,h,radius, color, precision); 195 } 196 void fillEllipse(int x, int y, int radiusW, int radiusH = -1, int degrees = 360, HipColor color = HipColor.no, int precision = 24) 197 { 198 manageBatchChange(geoBatch); 199 geoBatch.fillEllipse(x,y,radiusW,radiusH,degrees,color,precision); 200 } 201 void fillTriangle(int x1, int y1, int x2, int y2, int x3, int y3, HipColor color = HipColor.no) 202 { 203 manageBatchChange(geoBatch); 204 geoBatch.fillTriangle(x1,y1,x2,y2,x3,y3,color); 205 } 206 207 void drawSprite(IHipTexture texture, ubyte[] vertices) 208 { 209 manageBatchChange(spBatch); 210 spBatch.draw(texture, vertices); 211 } 212 void drawRegion(IHipTextureRegion reg, int x, int y, int z = 0, const HipColor color = HipColor.white, float scaleX = 1, float scaleY = 1, float rotation = 0) 213 { 214 manageBatchChange(spBatch); 215 spBatch.draw(reg, x, y, z, color, scaleX, scaleY, rotation); 216 } 217 void drawMap(IHipTilemap map) 218 { 219 manageBatchChange(spBatch); 220 map.render(spBatch, false); 221 } 222 223 void drawTexture(IHipTexture texture, int x, int y, int z = 0, const HipColor color = HipColor.white, float scaleX = 1, float scaleY = 1, float rotation = 0) 224 { 225 manageBatchChange(spBatch); 226 spBatch.draw(texture, x, y, z, color, scaleX, scaleY, rotation); 227 } 228 229 230 public import hip.util.data_structures : Array2D, Array2D_GC; 231 Array2D_GC!IHipTextureRegion cropSpritesheet( 232 IHipTexture t, 233 uint frameWidth, uint frameHeight, 234 uint width, uint height, 235 uint offsetX, uint offsetY, 236 uint offsetXPerFrame, uint offsetYPerFrame 237 ) 238 { 239 import hip.assets.texture; 240 import hip.util.lifetime; 241 return cast(typeof(return))hipSaveRef(HipTextureRegion.cropSpritesheet(t, 242 frameWidth, frameHeight, 243 width, height, 244 offsetX, offsetY, 245 offsetXPerFrame, offsetYPerFrame 246 ).toGC()); 247 } 248 249 void setFont(IHipFont font) 250 { 251 import hip.global.gamedef; 252 if(font is null) 253 textBatch.setFont(cast(IHipFont)HipDefaultAssets.font); 254 else 255 textBatch.setFont(font); 256 } 257 void setFontDeferred(IHipAssetLoadTask task) 258 { 259 import hip.global.gamedef; 260 if(task is null) 261 textBatch.setFont(cast(IHipFont)HipDefaultAssets.font); 262 else 263 textBatch.setFont(task); 264 } 265 266 void setTextColor(HipColor color) 267 { 268 manageBatchChange(textBatch); 269 textBatch.setColor(color); 270 } 271 void drawText(string text, int x, int y, HipColor color = HipColor.white, HipTextAlign alignH = HipTextAlign.LEFT, HipTextAlign alignV = HipTextAlign.CENTER, 272 int boundsWidth = -1, int boundsHeight = -1, bool wordWrap = false) 273 { 274 manageBatchChange(textBatch); 275 textBatch.setColor(color); 276 textBatch.draw(text, x, y, alignH, alignV, boundsWidth, boundsHeight, wordWrap); 277 } 278 279 void drawTextVertices(void[] vertices, IHipFont font) 280 { 281 manageBatchChange(textBatch); 282 textBatch.addVertices(vertices, font); 283 } 284 285 Array2D_GC!IHipTextureRegion cropSpritesheetRowsAndColumns(IHipTexture t, uint rows, uint columns) 286 { 287 uint frameWidth = t.getWidth() / columns; 288 uint frameHeight = t.getHeight() / rows; 289 return cropSpritesheet(t,frameWidth,frameHeight, t.getWidth, t.getHeight, 0, 0, 0, 0); 290 } 291 292 void finishRender2D() 293 { 294 if(geoBatch) geoBatch.flush(); 295 if(spBatch) spBatch.flush(); 296 if(textBatch) textBatch.flush(); 297 lastBatch = null; 298 sharedDepth = 0; 299 if(geoBatch) geoBatch.setCurrentDepth(0); 300 if(spBatch) spBatch.setCurrentDepth(0); 301 if(textBatch) textBatch.setCurrentDepth(0); 302 } 303 304 version(Standalone) 305 { 306 public import exportd; 307 }